package mammuthus.web.action

import java.util
import javax.servlet.http.HttpServletRequest
import com.alibaba.fastjson.serializer.SerializerFeature
import com.alibaba.fastjson.{JSON, JSONObject}
import mammuthus.web.service.{SlaveService, TestConfService}
import mammuthus.web.service.TestConfService
import net.liftweb.json
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.stereotype.Controller
import org.springframework.web.bind.annotation.{RequestParam, ResponseBody, RequestMapping}

import scala.beans.BeanProperty
import scala.collection.JavaConversions._
import net.sf.json.JSONArray
import mammuthus.web.db.TTestConf
import java.net.URLEncoder

import net.liftweb.{json => SJSon}
/**
 * Created by fengbingjian on 15/5/10 16:14.
 */
@Controller
@RequestMapping(Array("test"))
class TestAction extends ActionHelperTrait{

  implicit val formats = SJSon.Serialization.formats(SJSon.NoTypeHints)

  @Autowired
  @BeanProperty
  var testConfService:TestConfService = null

  @Autowired
  @BeanProperty
  var slaveService:SlaveService = null


  @RequestMapping(Array("addConf.html"))
  def addConf(httpServletRequest: HttpServletRequest,
               @RequestParam(value = "name", defaultValue = "") name: String,
               @RequestParam(value = "url", defaultValue =  "") url: String,
               @RequestParam(value = "host", defaultValue =  "") host: String,
               @RequestParam(value = "user", defaultValue =  "-") user: String
      ): String ={


    val r = testConfService.addConf(name, url,host,user)


    val json = new JSONObject()
    json.put("success", r._1)
    json.put("msg", r._2)

    httpServletRequest.setAttribute("page", "appManager")

    httpServletRequest.setAttribute("result", JSON.toJSONString(json,SerializerFeature.DisableCircularReferenceDetect))
    return "json"
  }

  @RequestMapping(Array("updateConf.html"))
  @ResponseBody
  def updateConf(httpServletRequest: HttpServletRequest,
              @RequestParam(value = "name", defaultValue = "") name: String,
              @RequestParam(value = "url", defaultValue =  "") url: String,
              @RequestParam(value = "host", defaultValue =  "") host: String,
              @RequestParam(value = "user", defaultValue =  "-") user: String
               ): String ={


    testConfService.updateConf(name, url,host,user)


      return """{"success": true}"""
  }

  @RequestMapping(Array("confDetail.html"))
  @ResponseBody
  def addConf(httpServletRequest: HttpServletRequest,
              @RequestParam(value = "name", defaultValue = "") name: String): String ={


    val r = testConfService.getTTestConf(name) match {
      case Some(x) => x
      case _ => new TTestConf(name, "", "", "")
    }


    SJSon.Serialization.write(r)

  }



  @RequestMapping(Array("list.html"))
  def list(httpServletRequest: HttpServletRequest,
              @RequestParam(value = "name", defaultValue = "") name: String,
              @RequestParam(value = "url", defaultValue =  "") url: String
               ): String ={


    httpServletRequest.setAttribute("result", testConfService.list())

    httpServletRequest.setAttribute("slave", slaveService.getSlave())

    httpServletRequest.setAttribute("page", "appManager")

    return  "testConfList"
  }


  @RequestMapping(Array("moduleDetail.html"))
  def moduleDetail(httpServletRequest: HttpServletRequest,
        @RequestParam(value = "name", defaultValue = "") name: String,
        @RequestParam(value = "host", defaultValue =  "") host: String
        ): String = {



    var list = slaveService.listDir(name, "/", host)

    val module:util.List[String] = list.filter(l => !l.isDirectory && l.getName.startsWith("launch_") && l.getName.endsWith(".sh") )
      .map(_.getName.replace("launch_", "").replace(".sh", "")).toList

    val testName = name
    //val moduleName = module.get(0)
    val msg = slaveService.appControl(testName, host,"status", "default", "launch.sh", true)
    //        val msg = slaveService.getTaskLog(taskId, host)
    //
    //        val json = JSON.parseArray(msg).getJSONObject(0).getString("message")

    val map:util.Map[String, Array[String]] = msg.split("\n").filter(_.startsWith("service ")).map(l => {
      val arr = l.split(" ")
      if(arr.length == 4)
        (arr(1), Array(arr(1), arr(2),arr(3)))
      else
        (arr(1),  Array(arr(1), arr(2)))

    }).toMap[String, Array[String]]

    val m:util.List[Array[_]] = module.map(l => if(map.containsKey(l)) map.get(l) else Array(l, "stop")).toList
//    httpServletRequest.setAttribute("module", map)



    httpServletRequest.setAttribute("result", JSON.toJSONString(m, SerializerFeature.DisableCheckSpecialChar))
    return "json"
  }

  @RequestMapping(Array("detail.html"))
  def detail(httpServletRequest: HttpServletRequest,
           @RequestParam(value = "name", defaultValue = "") name: String,
           @RequestParam(value = "host", defaultValue =  "") host: String,
           @RequestParam(value = "resultType", defaultValue =  "") resultType: String
            ): String ={
    val params = putToReqAttribute(httpServletRequest)

    if(List("hadoop","hbase").contains(params.getOrElse("app",name))){
       httpServletRequest.setAttribute("nav","yes")
       return "configureAndStartNav"
    }

    val hostArr = host.split(",")
    val testName = name //"test-" + name
    var list = slaveService.listDir(testName, "/", hostArr.last)
    val installed = if (list.size() == 0) false else true
    httpServletRequest.setAttribute("installed", installed)

    if(installed){

      val tag: util.List[String] = slaveService.appControl(testName, host,"git%20tag","default", "", true).split("\n").filter(!_.contains("fatal")).toList.reverse

      if(tag != null && tag.size() > 0) httpServletRequest.setAttribute("maxTag", tag.get(0))
      httpServletRequest.setAttribute("tag", tag)

    }


    httpServletRequest.setAttribute("installed", installed)
    httpServletRequest.setAttribute("name", name)
    httpServletRequest.setAttribute("url", testConfService.getUrl(name))

    httpServletRequest.setAttribute("host", host)

    httpServletRequest.setAttribute("page", "appManager")

    if(!name.startsWith("test-"))
      httpServletRequest.setAttribute("deployVersion", false)
    else
      httpServletRequest.setAttribute("deployVersion", true)

    return if(name.startsWith("test-") || hostArr.length == 1)  "testConfDetail" else "appManagerDetail"
  }




  @RequestMapping(Array("manager.html"))
  @ResponseBody
  def process(httpServletRequest: HttpServletRequest,
              @RequestParam(value = "name", defaultValue = "") name: String,
              @RequestParam(value = "module", defaultValue = "") module: String,
              @RequestParam(value = "host", defaultValue =  "") host: String,
              @RequestParam(value = "action", defaultValue =  "") action: String
               ): String = {

    val testName = name //"test-" + name

    //val id = slaveService.shell(testName, host, "shell", "git clone " + url + " " + testName)

//    val conf = Set("start", "stop", "stop_9", "all", "restart")
//    var cmd =
//      if(action.startsWith("tag ") ) (action + " " + slaveService.masterUrl + "/upload?" + slaveService.authTokenStr)
//      else if(conf.contains(action)) action + " " + slaveService.masterUrl + "/app/register?" + slaveService.authTokenStr
//      else action
    val cmd = action
    val taskId =  slaveService.appControl(name, host,  cmd.replace(" ", "%20"), "default", "launch_" + module + ".sh")

    return s"""{"taskId": "${taskId}" }"""
  }

  @RequestMapping(Array("install.html"))
  @ResponseBody
  def install(httpServletRequest: HttpServletRequest,
              @RequestParam(value = "name", defaultValue = "") name: String,
              @RequestParam(value = "host", defaultValue =  "") host: String
               ): String = {

    val testName = name //"test-" + name

    //val id = slaveService.shell(testName, host, "shell", "git clone " + url + " " + testName)

    val tConf = testConfService.getTTestConf(deleteTestPrefix(name)).get



    val abc = slaveService.install(testName,"1.0",host,tConf.url.replace(" ", "%20").replace("&", "%26"),tConf.user)

    val taskId = JSONArray.fromObject(abc).getJSONObject(0).getJSONObject("task").getString("taskId")
    //val taskId =  slaveService.shell(name, host, "shell", s"cd /data/1/usr/local/applications/ && git clone ${url} ${testName}".replace(" ", "%20").replace("&", "%26"))
    return s"""{"taskId": "${taskId}" }"""
  }

  @RequestMapping(Array("update.html"))
  @ResponseBody
  def update(httpServletRequest: HttpServletRequest,
              @RequestParam(value = "name", defaultValue = "") name: String,
              @RequestParam(value = "host", defaultValue =  "") host: String
               ): String = {

    val testName = name //"test-" + name

    //val id = slaveService.shell(testName, host, "shell", "git clone " + url + " " + testName)

    val command = s"cd /data/1/usr/local/applications/${testName} && git pull"

    val taskId =  slaveService.shell(name, host, "shell", wrapWithUser(name,command))

    return s"""{"taskId": "${taskId}" }"""
  }

  def deleteTestPrefix(appName:String) = {
    if(appName.startsWith("test-")) appName.split("test-")(1) else appName
  }
  def wrapWithUser(appName:String,command:String) = {
    val user = TTestConf.find(deleteTestPrefix(appName)) match {
      case Some(x) => x.user
      case None => ""
    }
    if(user != null && !user.isEmpty && user !="-" ) URLEncoder.encode(s"su - $user /bin/bash -c '$command'","utf-8")
    else URLEncoder.encode(command,"utf-8")
  }

  @RequestMapping(Array("taskLog.html"))
  @ResponseBody
  def taskLog(httpServletRequest: HttpServletRequest,
              @RequestParam(value = "taskId", defaultValue = "") taskId: String,
              @RequestParam(value = "host", defaultValue =  "") host: String,
              @RequestParam(value = "offset", defaultValue =  "-1") offset: Int
               ): String = {

    //val testName = "test-" + name
//
//    //val id = slaveService.shell(testName, host, "shell", "git clone " + url + " " + testName)
//
//    val url = testConfService.getUrl(name)
//    val taskId =  slaveService.shell(name, host, "shell", s"cd /data/1/usr/local && git clone ${url} ${testName}".replace(" ", "%20"))

    slaveService.getTaskLog(taskId, host, offset)
    //return s"""{"taskId": "${taskId}" }"""
  }


}
